package com.weidong.mybbs.config;

import com.weidong.mybbs.config.frontmenu.FrontMenu;
import org.apache.commons.lang3.StringUtils;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.validation.constraints.NotNull;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

@Component
@ConditionalOnProperty(prefix = "bbs.front-menu",name = "enable",havingValue = "true")
@PropertySource(value = "${bbs.front-menu.config-property-file:classpath:front-menu.properties}",encoding = "utf-8")
@ConfigurationProperties(prefix = "bbs.front-menu")
public class FrontMenuConfig {

    private List<FrontMenu> list;

    public List<FrontMenu> getList() {
        return list;
    }

    public void setList(List<FrontMenu> list) {
        this.list = list;
    }


    /**
     * 获取tree结构菜单
     * @return
     */
    public List<FrontMenu> getAsTree(@NotNull Set<String> permissionKeys){
        List<FrontMenu> menus = new ArrayList<>();
        if (permissionKeys == null || permissionKeys.isEmpty()){
            return menus;
        }

        //取出具备权限的菜单
        list.forEach(lo -> {
            String pkey = lo.getPermissionKey();
            if (StringUtils.isNotBlank(pkey)){
                if (permissionKeys.stream().anyMatch(p -> p.equals(pkey))){
                    menus.add(lo);
                    //将父菜单链放到列表
                    if (!"0".equals(lo.getParentKey())){
                        //非根菜单，找到父菜单添加到列表
                        //如果已添加 则不添加
                        if (menus.stream().noneMatch(ex -> ex.getKey().equals(lo.getParentKey()))){
                            String parentKey = lo.getParentKey();
                            boolean hasNext = false;
                            do {

                                for (FrontMenu lp:list) {
                                    if (lp.getKey().equals(parentKey)){
                                        parentKey = lp.getParentKey();
                                        if (menus.stream().noneMatch(ex -> ex.getKey().equals(lp.getKey()))){
                                            menus.add(lp);
                                        }
                                        hasNext = true;
                                    }
                                }
                            }while (hasNext && !"0".equals(parentKey));
                        }
                    }
                }
            }
        });

        //递归构建tree列表数据
        return buildTreeList(menus,null);
    }


    private List<FrontMenu> buildTreeList(List<FrontMenu> list,List<FrontMenu> parents){
        if (list == null || list.size() == 0){
            return new ArrayList<>();
        }
        //找出根菜单
        if (parents == null || parents.size() == 0){
            parents = list.stream().filter(fm -> fm.getParentKey().equals("0")).collect(Collectors.toList());
            list.removeIf(fm->"0".equals(fm.getParentKey()));
        }

        if (parents.size() > 0 && list.size() > 0){
            parents.forEach(pt ->{
                //找出子菜单
                List<FrontMenu> subMenus = list.stream().filter(fm->fm.getParentKey().equals(pt.getKey())).collect(Collectors.toList());
                list.removeIf(fm->fm.getParentKey().equals(pt.getKey()));
                if (subMenus.size() > 0){
                    if (list.size() > 0){
                        subMenus = buildTreeList(list,subMenus);
                    }
                    pt.setSubMenus(subMenus);

                }
            });
        }

        return parents;
    }

    /**
     * 验证菜单
     */
    @PostConstruct
    public void validate(){
        list.forEach(frontMenu -> {
            frontMenu.setKey(StringUtils.trimToNull(frontMenu.getKey()));
            frontMenu.setTitle(StringUtils.trimToNull(frontMenu.getTitle()));
            frontMenu.setUri(StringUtils.trimToNull(frontMenu.getUri()));
            frontMenu.setIcon(StringUtils.trimToNull(frontMenu.getIcon()));
            frontMenu.setParentKey(StringUtils.trimToNull(frontMenu.getParentKey()));
            frontMenu.setPermissionKey(StringUtils.trimToNull(frontMenu.getPermissionKey()));
            if (StringUtils.isBlank(frontMenu.getKey())){
                throw new RuntimeException("每个菜单都必须有一个唯一主键");
            }
            if (1 != list.stream().filter(f -> f.getKey().equals(frontMenu.getKey())).count()){
                throw new RuntimeException("菜单主键Key重复<Key="+frontMenu.getKey()+">");
            }
            if (StringUtils.isBlank(frontMenu.getTitle())){
                throw new RuntimeException("菜单必须配置标题<key="+frontMenu.getKey()+">");
            }

            if (StringUtils.isBlank(frontMenu.getParentKey())){
                frontMenu.setParentKey("0");
            }

            if (StringUtils.isBlank(frontMenu.getPermissionKey())){
                if (!"0".equals(frontMenu.getParentKey())){
                    throw new RuntimeException("非根菜单必须配置校验权限<name="+frontMenu.getTitle()+">");
                }else{
                    //没有子菜单的根菜单必须配置验证权限key
                    if (list.stream().noneMatch(sm -> sm.getParentKey().equals(frontMenu.getKey()))){
                        throw new RuntimeException("没有子菜单的根菜单必须配置校验权限<name="+frontMenu.getTitle()+">");
                    }
                }
            }

            if (!"0".equals(frontMenu.getParentKey())){
                //检查是否含有父菜单
                String parentKey = frontMenu.getParentKey();
                boolean hasNext = false;
                do {
                    FrontMenu parent = null;
                    for (FrontMenu f:list) {
                        if (f.getKey().equals(parentKey)){
                            parent = f;
                            break;
                        }
                    }
                    if (parent == null){
                        throw new RuntimeException("菜单<name="+frontMenu.getTitle()+">未找到父菜单<parentKey="+frontMenu.getParentKey()+">");
                    }

                    if (!"0".equals(parent.getParentKey())){
                        hasNext = true;
                        parentKey = parent.getParentKey();
                    }

                }while (hasNext && "0".equals(parentKey));
            }
        });
    }
}
